home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Communications / pcomm / Source / input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-12  |  11.0 KB  |  527 lines

  1. /*
  2.  * The input routines.  This program runs as a child process to the
  3.  * Pcomm program.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <signal.h>
  8. #include <setjmp.h>
  9. #define MAIN
  10. #include "config.h"
  11. #include "misc.h"
  12. #include "status.h"
  13. #include "vcs.h"
  14.  
  15. #ifdef SHAREDMEM
  16. #include <sys/types.h>
  17. #include <sys/ipc.h>
  18. #include <sys/shm.h>
  19. #endif /* SHAREDMEM */
  20.  
  21. jmp_buf i_jmp;
  22. int vcs_param[NUM_VCS][5];        /* positional parameters */
  23. int vcs_opt[NUM_VCS][10];        /* options unique to each VCS */
  24. int vcs_codes[NUM_VCS][VCS_SIZE];    /* the VCS codes */
  25. int vcs_leadin[NUM_VCS];        /* unique list of lead-in characters */
  26. int num_leadin;                /* length of lead-in list */
  27. int hold, max_row, max_col, skip_row;
  28. FILE *logfp, *lprfp;
  29. struct STATUS *status;
  30.  
  31. #ifdef SHAREDMEM
  32. #define VROW    status->row
  33. #define VCOL    status->col
  34. #define VS    status->vs
  35. #else /* SHAREDMEM */
  36. int VROW, VCOL;
  37. char VS[MAX_ROW][MAX_COL];
  38. struct STATUS s;
  39. #endif /* SHAREDMEM */
  40.  
  41. /*
  42.  * Read the serial port and write the characters to the screen.  Watch
  43.  * for signals from the parent process to toggle the fancy options.
  44.  * Writes the characters received to a virtual screen buffer.
  45.  */
  46.  
  47. main(argc, argv)
  48. int argc;
  49. char *argv[];
  50. {
  51.     FILE *popen();
  52.     register int in_cnt, out_cnt;
  53.     int got_sig();
  54.     char c, *strcpy(), *bufp, in_buf[INPUT_BUF], out_buf[INPUT_BUF*2];
  55.     void _exit(), exit(), vcs_table(), setbuf(), vs_putchar(), vs_clear();
  56. #ifdef SHAREDMEM
  57.     int shm_id;
  58.     char *shmat();            /* comment out, if required */
  59.     void perror();
  60. #endif /* SHAREDMEM */
  61.                     /* set the trap for the signals */
  62.     signal(SIGALRM, SIG_IGN);
  63.     signal(SIGHUP,  SIG_IGN);
  64.     signal(SIGQUIT, SIG_IGN);
  65.     signal(SIGUSR1, (SIG_TYPE(*) ()) got_sig);
  66.     signal(SIGUSR2, (SIG_TYPE(*) ()) got_sig);
  67.     signal(SIGINT,  (SIG_TYPE(*) ()) got_sig);
  68.     signal(SIGTERM, (SIG_TYPE(*) ()) got_sig);
  69.  
  70.     setbuf(stdout, (char *) NULL);
  71.                     /* for the curious... */
  72.     if (argc == 1) {
  73.         fprintf(stderr, "This is the input routine for the Pcomm program\n");
  74.         fprintf(stderr, "It is not designed to be run as a separate program\n");
  75.         exit(1);
  76.     }
  77.  
  78. #ifdef SHAREDMEM
  79.     shm_id = atoi(argv[1]);
  80.     status = (struct STATUS *) shmat(shm_id, (char *) 0, 0);
  81.     if ((int) status == -1) {
  82.         perror("shmat");
  83.         _exit(1);
  84.     }
  85. #else /* SHAREDMEM */
  86.     status = &s;
  87. #endif /* SHAREDMEM */
  88.                     /* load the VCS table */
  89.     vcs_table();
  90.     if (max_row > MAX_ROW)
  91.         max_row = MAX_ROW;
  92.     if (max_col > MAX_COL-1)
  93.         max_col = MAX_COL-1;
  94.                     /* parse the command line */
  95. #ifndef SHAREDMEM
  96.     status->fd = atoi(argv[1]);
  97.     status->dup_fd = atoi(argv[2]);
  98.     status->add_lf = atoi(argv[3]);
  99.     status->log = atoi(argv[4]);
  100.     status->print = atoi(argv[5]);
  101.     strcpy(status->log_path, argv[6]);
  102.     strcpy(status->vs_path, argv[7]);
  103. #endif /* SHAREDMEM */
  104.  
  105.     skip_row = 0;
  106.  
  107. #ifdef SHAREDMEM
  108.     if (status->clr)
  109.         skip_row = 1;
  110. #else /* SHAREDMEM */
  111.                     /* read previous screen */
  112.     if (!access(status->vs_path, 0))
  113.         read_vs();
  114.     else
  115.         skip_row = 1;
  116. #endif /* SHAREDMEM */
  117.  
  118.     hold = 0;
  119.                     /* start up file pointers */
  120.     lprfp = (FILE *) NULL;
  121.     logfp = (FILE *) NULL;
  122.  
  123.     switch (setjmp(i_jmp)) {
  124.         case 0:            /* no signal */
  125.             break;
  126.         case 1:            /* toggle the data logging */
  127.             status->log = status->log ? 0 : 1;
  128.             break;
  129.         case 2:            /* toggle the printer */
  130.             status->print = status->print ? 0 : 1;
  131.             break;
  132.         case 3:            /* suspend the input */
  133.             hold = hold ? 0 : 1;
  134. #ifndef SHAREDMEM
  135.             if (hold)
  136.                 write_vs();
  137. #endif /* SHAREDMEM */
  138.             break;
  139.         case 4:            /* clean up and go home */
  140.             if (status->log)
  141.                 fclose(logfp);
  142.             if (status->print) {
  143.                 putc('\f', lprfp);
  144.                 pclose(lprfp);
  145.             }
  146. #ifdef SHAREDMEM
  147.                     /* detach shared memory */
  148.             shmdt((char *) status);
  149. #endif /* SHAREDMEM */
  150.             _exit(0);
  151.             break;
  152.     }
  153.                     /* any signal will awaken pause() */
  154.     if (hold)
  155. #ifdef BSD
  156.         sigpause(0);
  157. #else /* BSD */
  158.         pause();
  159. #endif /* BSD */
  160.                     /* open or close the printer */
  161.     if (status->print && lprfp == NULL)
  162.         lprfp = popen(LPR, "w");
  163.  
  164.     if (!status->print && lprfp != NULL) {
  165.         putc('\f', lprfp);
  166.         pclose(lprfp);
  167.         lprfp = (FILE *) NULL;
  168.     }
  169.                     /* open or close the log file */
  170.     if (status->log && logfp == NULL) {
  171.         if (strcmp(status->log_path, "NOT_DEFINED")) {
  172.             if (!(logfp = fopen(status->log_path, "a")))
  173.                 status->log = 0;
  174.         }
  175.         else
  176.             status->log = 0;
  177.     }
  178.     if (!status->log && logfp != NULL) {
  179.         fclose(logfp);
  180.         logfp = (FILE *) NULL;
  181.     }
  182.  
  183. #ifdef SHAREDMEM
  184.     if (status->clr) {
  185.         status->clr = 0;
  186.         vs_clear();
  187.     }
  188. #else /* SHAREDMEM */
  189.                     /* clear if vs_path doesn't exist */
  190.     if (access(status->vs_path, 0))
  191.         vs_clear();
  192. #endif /* SHAREDMEM */
  193.  
  194.     /*
  195.      * The very first screen we see after dialing has the "Connected to..."
  196.      * message at row 0, therefore we start our virtual screen at row 1.
  197.      */
  198.     if (skip_row) {
  199.         skip_row = 0;
  200.         VROW = 1;
  201.     }
  202.                     /* here we go... */
  203.     while (1) {
  204.         if ((in_cnt = read(status->fd, in_buf, INPUT_BUF)) <= 0)
  205.             continue;
  206.         /*
  207.          * If we're inside an auto-login shell script, send a
  208.          * duplicate of the input to Pcomm. (This a kludge and is
  209.          * only used where performance isn't an issue).
  210.          */
  211.         if (status->dup_fd != -1)
  212.             write(status->dup_fd, in_buf, in_cnt);
  213.  
  214.                     /* "peel" the buffer one at a time */
  215.         out_cnt = 0;
  216.         bufp = in_buf;
  217.         while (--in_cnt >= 0) {
  218.             c = *bufp++ & 0xff;
  219.                     /* send to logfile */
  220.             if (status->log) {
  221.                 if (c == '\r' && status->add_lf)
  222.                     putc('\n', logfp);
  223.                     /* no carriage returns in logfile */
  224.                 if (c != '\r')
  225.                     putc(c, logfp);
  226.             }
  227.                     /* send to printer too? */
  228.             if (status->print)
  229.                 putc(c, lprfp);
  230.  
  231.                     /* put a char in virtual screen */
  232.             vs_putchar(c);
  233.  
  234.                     /* build the output buffer */
  235.             out_buf[out_cnt++] = c;
  236.             if (c == '\r' && status->add_lf)
  237.                 out_buf[out_cnt++] = '\n';
  238.  
  239.                     /* output in smaller chunks */
  240.             if (out_cnt >= OUTPUT_BUF) {
  241.                 fwrite(out_buf, sizeof(char), out_cnt, stdout);
  242.                 out_cnt = 0;
  243.             }
  244.         }
  245.         if (out_cnt)
  246.             fwrite(out_buf, sizeof(char), out_cnt, stdout);
  247.     }
  248. }
  249.  
  250. /*
  251.  * Figure out which signal we just received, and fix the return code of
  252.  * the setjmp function above to the proper value.
  253.  */
  254.  
  255. int
  256. got_sig(sig)
  257. int sig;
  258. {
  259.     switch (sig) {
  260.         case SIGUSR1:
  261.             signal(SIGUSR1, (SIG_TYPE(*) ()) got_sig);
  262.             longjmp(i_jmp, 1);
  263.         case SIGUSR2:
  264.             signal(SIGUSR2, (SIG_TYPE(*) ()) got_sig);
  265.             longjmp(i_jmp, 2);
  266.         case SIGINT:
  267.             signal(SIGINT, (SIG_TYPE(*) ()) got_sig);
  268.             longjmp(i_jmp, 3);
  269.         case SIGTERM:
  270.             signal(SIGTERM, (SIG_TYPE(*) ()) got_sig);
  271.             longjmp(i_jmp, 4);
  272.     }
  273. }
  274.  
  275. /*
  276.  * Put a character in the virtual screen.  This routine saves incoming
  277.  * characters in a two dimensional buffer designed to mimic the real
  278.  * screen.
  279.  */
  280.  
  281. void
  282. vs_putchar(c)
  283. char c;
  284. {
  285.     register int i;
  286.     char *memset();
  287.     int tab_stop;
  288.     void vs_scroll();
  289.  
  290.     switch (vcs_filter(c)) {
  291.         case MAYBE:        /* wait and see... */
  292.             break;
  293.         case 256+HOME:        /* home virtual screen "cursor" */
  294.             VROW = 0;
  295.             VCOL = 0;
  296.             break;
  297.         case 256+CLR_EOL:    /* clear to end of line */
  298.             memset(&VS[VROW][VCOL], ' ', max_col - VCOL);
  299.             VCOL = max_col -1;
  300.             break;
  301.         case 256+CLR_EOS:    /* clear to end of screen */
  302.             memset(&VS[VROW][VCOL], ' ', max_col - VCOL);
  303.             for (i=VROW+1; i<max_row; i++)
  304.                 memset(VS[i], ' ', max_col);
  305.             VROW = max_row -1;
  306.             VCOL = max_col -1;
  307.             break;
  308.         case 256+CLEAR:        /* clear all and home "cursor" */
  309.             for (i=0; i<max_row; i++)
  310.                 memset(VS[i], ' ', max_col);
  311.             VROW = 0;
  312.             VCOL = 0;
  313.             break;
  314.         case 256+MV_UP:        /* move "cursor" up */
  315.             VROW--;
  316.             if (VROW < 0)
  317.                 VROW = 0;
  318.             break;
  319.         case 256+MV_DOWN:    /* move "cursor" down */
  320.             VROW++;
  321.             if (VROW >= max_row)
  322.                 VROW = max_row -1;
  323.             break;
  324.         case 256+MV_RIGHT:    /* move "cursor" right */
  325.             VCOL++;
  326.             if (VCOL >= max_col)
  327.                 VCOL = max_col -1;
  328.             break;
  329.         case 256+MV_LEFT:    /* move "cursor" left */
  330.         case BS:        /* non destructive back space */
  331.             VCOL--;
  332.             if (VCOL < 0)
  333.                 VCOL = 0;
  334.             break;
  335.         case 256+MV_DIRECT:    /* direct cursor movement */
  336.             VROW = vcs_param[MV_DIRECT][0];
  337.             VCOL = vcs_param[MV_DIRECT][1];
  338.  
  339.                     /* if "add one" and "decimal" */
  340.             if (vcs_opt[MV_DIRECT][0] && vcs_opt[MV_DIRECT][1]) {
  341.                 VROW--;
  342.                 VCOL--;
  343.             }
  344.                     /* if "character" */
  345.             if (vcs_opt[MV_DIRECT][2]) {
  346.                     /* if "add offset" */
  347.                 if (vcs_opt[MV_DIRECT][3]) {
  348.                     VROW -= vcs_opt[MV_DIRECT][5];
  349.                     VCOL -= vcs_opt[MV_DIRECT][5];
  350.                 }
  351.                     /* if "subtract offset" */
  352.                 if (vcs_opt[MV_DIRECT][4]) {
  353.                     VROW += vcs_opt[MV_DIRECT][5];
  354.                     VCOL += vcs_opt[MV_DIRECT][5];
  355.                 }
  356.                 VROW--;
  357.                 VCOL--;
  358.             }
  359.             break;
  360.         case 0:
  361.         case 7:            /* skip NULL and "bell" character */
  362.             break;
  363.         case '\t':        /* tab character */
  364.             tab_stop = VCOL + 8 - (VCOL % 8);
  365.                     /* if wrap around */
  366.             if (tab_stop >= max_col) {
  367.                     /* spaces up to eol */
  368.                 memset(&VS[VROW][VCOL], ' ', max_col - VCOL);
  369.                 VROW++;
  370.                 if (VROW >= max_row)
  371.                     vs_scroll();
  372.  
  373.                     /* the remainder of the tab */
  374.                 VCOL = tab_stop - max_col;
  375.             }
  376.             else {
  377.                 memset(&VS[VROW][VCOL], ' ', tab_stop - VCOL);
  378.                 VCOL = tab_stop;
  379.             }
  380.             break;
  381.         case '\r':        /* carriage return */
  382.             VCOL = 0;
  383.             if (!status->add_lf)
  384.                 break;
  385.             /* fall thru...*/
  386.         case '\n':        /* line feed */
  387.             VROW++;
  388.             if (VROW >= max_row)
  389.                 vs_scroll();
  390.             break;
  391.         default:        /* a normal character */
  392.             VS[VROW][VCOL] = c;
  393.             VCOL++;
  394.                     /* wrap around */
  395.             if (VCOL >= max_col) {
  396.                 VCOL = 0;
  397.                 VROW++;
  398.                 if (VROW >= max_row)
  399.                     vs_scroll();
  400.             }
  401.             break;
  402.     }
  403.     return;
  404. }
  405.  
  406. #ifndef SHAREDMEM
  407. /*
  408.  * Save the virtual screen to a file.
  409.  */
  410.  
  411. int
  412. write_vs()
  413. {
  414.     FILE *fp;
  415.     register int i;
  416.  
  417.     if (!(fp = fopen(status->vs_path, "w")))
  418.         return(1);
  419.                     /* current x y coordinates */
  420.     fprintf(fp, "%d,%d\n", VROW, VCOL);
  421.  
  422.     for (i=0; i<max_row; i++) {
  423.         VS[i][max_col] = '\0';
  424.         fprintf(fp, "%s\n", VS[i]);
  425.     }
  426.     fclose(fp);
  427.     return(0);
  428. }
  429.  
  430. /*
  431.  * Get the virtual screen image from the file.  Since input() gets
  432.  * killed from time to time, the vs_path file is the only way to retain
  433.  * the screen image.
  434.  */
  435.  
  436. int
  437. read_vs()
  438. {
  439.     FILE *fp;
  440.     register int i;
  441.     char buf[10];
  442.                     /* in case the fopen fails... */
  443.     VROW = 0;
  444.     VCOL = 0;
  445.                     /* not guaranteed to exist yet */
  446.     if (!(fp = fopen(status->vs_path, "r")))
  447.         return(1);
  448.                     /* get the x, y coordinates */
  449.     fgets(buf, 10, fp);
  450.     sscanf(buf, "%d,%d\n", &VROW, &VCOL);
  451.  
  452.                     /* read the file into the vs array */
  453.     for (i=0; i<max_row; i++) {
  454.         fgets(VS[i], MAX_COL, fp);
  455.         VS[i][max_col] = '\0';
  456.     }
  457.     fclose(fp);
  458.     return(0);
  459. }
  460. #endif /* SHAREDMEM */
  461.  
  462. /*
  463.  * If the user clears the screen with the ^A-C command, the input
  464.  * has to be in sync.
  465.  */
  466.  
  467. void
  468. vs_clear()
  469. {
  470.     register int i;
  471.     char *memset();
  472.  
  473.     for (i=0; i<max_row; i++)
  474.         memset(VS[i], ' ', max_col);
  475.                     /* home the "cursor" */
  476.     VROW = 0;
  477.     VCOL = 0;
  478.     return;
  479. }
  480.  
  481. /*
  482.  * Do a software scroll on the virtual screen.  Does not alter the
  483.  * "col" variable.
  484.  */
  485.  
  486. void
  487. vs_scroll()
  488. {
  489.     char *strcpy(), *memset();
  490.                     /* move 'em up 1 line */
  491. #ifdef MEMMOVE
  492.     char *MEMMOVE();
  493.  
  494.     MEMMOVE(VS[0], VS[1], (max_row -1) * MAX_COL);
  495. #else /* MEMMOVE */
  496.     register int i;
  497.  
  498.     for (i=0; i<max_row-1; i++)
  499.         strcpy(VS[i], VS[i+1]);
  500. #endif /* MEMMOVE */
  501.                     /* clear the bottom line */
  502.     memset(VS[max_row-1], ' ', max_col);
  503.  
  504.     VROW = max_row -1;
  505.     return;
  506. }
  507.  
  508. #ifdef BSD
  509. /*
  510.  * Copies the character c, n times to string str
  511.  */
  512.  
  513. /* char *
  514. memset(str, c, n)
  515. char *str, c;
  516. int n;
  517. {
  518.     char *s1 = str;
  519.  
  520.     while (n > 0) {
  521.         --n;
  522.         *s1++ = c;
  523.     }
  524.     return(str);
  525. }  */
  526. #endif /* BSD */
  527.